package com.tiny.diamond.internal.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;

public class StreamUtil {

    private static final int DEFAULT_BUFFER_SIZE = 8192;

    public static void io(InputStream inputStream, OutputStream outputStream) throws IOException {
        io(inputStream, outputStream, -1);
    }

    /**
     * 读取输入流并写入输出流
     * @param inputStream
     * @param outputStream
     * @param bufferSize 当值为-1 时,使用默认size。
     * @throws IOException
     */
    public static void io(InputStream inputStream, OutputStream outputStream, int bufferSize) throws IOException {
        if (bufferSize == -1) {
            bufferSize = DEFAULT_BUFFER_SIZE;
        }
        byte[] buffer = new byte[bufferSize];
        int amount;

        while ((amount = inputStream.read(buffer)) >= 0) {
            outputStream.write(buffer, 0, amount);
        }
    }

    public static void io(Reader in,Writer out) throws IOException {
        io(in, out,-1);
    }

    public static void io(Reader in, Writer out, int bufferSize) throws IOException {
        if (bufferSize == -1){
            bufferSize = DEFAULT_BUFFER_SIZE >> 1;
        }
        char[] buffer = new char[bufferSize];
        int amount;

        while ((amount = in.read(buffer)) >= 0) {
            out.write(buffer, 0, amount);
        }
    }

    public static String readText(InputStream inputStream) throws IOException {
        return readText(inputStream,null,-1);
    }

    public static String readText(InputStream inputStream,String encoding) throws IOException {
        return readText(inputStream ,encoding,-1);
    }

    public static String readText(InputStream inputStream,String encoding, int bufferSize) throws IOException {
        Reader reader = (encoding == null)? new InputStreamReader(inputStream) : new InputStreamReader(inputStream,encoding);
        return readText(reader, bufferSize);
    }

    public static String readText(Reader reader) throws IOException {
        return readText(reader, -1);
    }

    public static  String readText(Reader reader, int bufferSize) throws IOException {
        StringWriter writer = new StringWriter();
        io(reader, writer, bufferSize);
        return writer.toString();
    }

    public static OutputStream synchronizedOutputStream(OutputStream out) {
        return new SynchronizedOutputStream(out);
    }

    public static OutputStream synchronizedOutputStream(OutputStream out, Object lock) {
        return new SynchronizedOutputStream(out, lock);
    }

    private static class SynchronizedOutputStream extends OutputStream {
        private OutputStream out;
        private Object lock;

        SynchronizedOutputStream(OutputStream out) {
            this(out, out);
        }

        SynchronizedOutputStream(OutputStream out, Object lock) {
            this.out = out;
            this.lock = lock;
        }

        public void write(int datum) throws IOException {
            synchronized (lock) {
                out.write(datum);
            }
        }

        public void write(byte[] data) throws IOException {
            synchronized (lock) {
                out.write(data);
            }
        }

        public void write(byte[] data, int offset, int length) throws IOException {
            synchronized (lock) {
                out.write(data, offset, length);
            }
        }

        public void flush() throws IOException {
            synchronized (lock) {
                out.flush();
            }
        }

        public void close() throws IOException {
            synchronized (lock) {
                out.close();
            }
        }
    }


}
